package ui;

import info.Manuscript;
import info.Recommendation;
import info.Review;
import io.ManHasRevAccess;
import io.ManuscriptAccess;
import io.RecommendationAccess;
import io.ReviewAccess;
import io.RoleAccess;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;




import org.jdom2.JDOMException;

import users.ProgramChair;
import users.Role;
import users.User;

/**
 * The primary panel that the Program Chair will use to carry out his or her duties.
 * 
 * @author Aaron Chen
 * @version 3/9/2014
 */
@SuppressWarnings("serial")
public class ProgramChairPanel extends AbstractMainComponent implements Recipient {
  
  /** The label that displays the names of all currently assigned Subprogram Chairs. */
  private JLabel my_lbl_spcs;
  
  /** The table of information that displays a quick summary of the manuscripts'
   * reviews and recommendations received so far. */
  private JTable my_table;
  
  /** The Program Chair role object that belongs to the user. */
  private ProgramChair my_program_chair;
  
  
  /**
   * Create the internal frame, which acts as a panel.
   * @param the_parent  the display panel. 
   * @param the_pc the program chair. 
   */
  public ProgramChairPanel(final DisplayPanel the_parent, final ProgramChair the_pc) {
    super(the_parent);
    setFrameParameters();
    my_program_chair = the_pc;
    final JPanel main_panel = createMainPanel();
    add(main_panel);
  }
  
  
  /**
   * Create the main panel.
   * @return The main panel.
   */
  private JPanel createMainPanel() {
    final JPanel panel_main = new JPanel();
    
    my_table = createTable();
    
//    final TableColumnModel column_model = my_table.getColumnModel();
//    final int n = Math.min(column_model.getColumnCount(), TABLE_PREFERRED_WIDTH.length);
//    for (int i = 0; i < n; i++) {
//      column_model.getColumn(i).setPreferredWidth(TABLE_PREFERRED_WIDTH[i]);
//    }
    my_lbl_spcs = new JLabel();
    buildSPCLabelText();
    
    final JButton btn_add_spc = new JButton("Add Subprogram Chair...");
    btn_add_spc.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(final ActionEvent the_e) {
        final DisplayPanel dsp = getDisplayStack();
        final UserListPanel ulp = new UserListPanel(dsp, ProgramChairPanel.this);
        dsp.addToStack(ulp);
      }
    });
    
    panel_main.add(my_lbl_spcs);
    panel_main.add(btn_add_spc);
    panel_main.add(my_table.getTableHeader());
    panel_main.setLayout(new BoxLayout(panel_main, BoxLayout.Y_AXIS));
    panel_main.add(my_table);

    return panel_main;
  }
  
  /**
   * Creates the table that summarizes the status of each submitted manuscript.
   * <p>
   * The table will display the manuscript author, title, and the decision status
   * on whether the manuscript was accepted, rejected, or no decision.  Review
   * ratings from the reviewers and subprogram chair can either show no assigned
   * individual, no submitted rating, or a rating from 1 to 5.
   * @return The table that summarizes the status of each manuscript.
   */
  private JTable createTable() {
    final ManuscriptAccess manuscript_access = getDatabase().accessManuscript();
    final List<Long> manuscripts =
        manuscript_access.getViewableManuscripts(my_program_chair.getUser().getID(),
                                                 my_program_chair.getConferenceID(),
                                                 my_program_chair.getRoleID()); 
    final int num_rows = manuscripts.size();
    int num_max_reviews = 1;
    final List<List<Long>> list_reviews = new ArrayList<List<Long>>(num_rows);
    for (Long m : manuscripts) {
      ManHasRevAccess temp = null;
      try {
        temp = new ManHasRevAccess();
      } catch (final IOException e) {
        e.printStackTrace();
      } catch (final JDOMException e) {
        e.printStackTrace();
      }
      final List<Long> review_ids = temp.getReviewID(m);
      if (review_ids.size() > num_max_reviews) {
        num_max_reviews = review_ids.size();
      }
      list_reviews.add(review_ids);
    }
    final int num_columns = 4 + num_max_reviews;
    
    final String[] headers = new String[num_columns];
    headers[0] = "Author";
    headers[1] = "Manuscript";
    headers[num_columns - 2] = "SPC";
    headers[num_columns - 1] = "Decision";
    for (int i = 1; i <= num_max_reviews; i++) {
      headers[1 + i] = "R" + i;
    }
    
    //Setup for the loop
    final Object[][] data = new Object[num_rows][num_columns];
    final ActionListener[][] als = new ActionListener[num_rows][num_columns];
    final Iterator<Long> manu_itr = manuscripts.iterator();
    final Iterator<List<Long>> list_itr = list_reviews.iterator();
    for (int i = 0; i < data.length; i++) {
      
      //Populating the manuscript submitting author and title columns
      final Long manu_id = manu_itr.next();
      final Manuscript manu = MainPage.getDatabase().accessManuscript().getManuscript(manu_id);
      data[i][0] = manu.getSubmittingAuthor();
      data[i][1] = manu.getTitle();
      als[i][1] = new ActionListener() {
        @Override
        public void actionPerformed(final ActionEvent the_e) {
          final DisplayPanel dsp = getDisplayStack();
          final ManuscriptViewingPanel msp =
              new ManuscriptViewingPanel(dsp, manu, my_program_chair);
          dsp.addToStack(msp);
        }
      };
      
      //Populating the review columns
      final ReviewAccess review_access = getDatabase().accessRev();
      final List<Long> reviews = list_itr.next();
      final Iterator<Long> rev_itr = reviews.iterator();
      for (int j = 0; j < reviews.size(); j++) {
        final Review rev = review_access.getReview(rev_itr.next());
        if (rev != null) {
          final int rating = rev.getSummaryRating();
          if (rating <= 0) {
            data[i][2 + j] = "-";
          } else {
            data[i][2 + j] = rating;
          }
        }
      }
      
      //Populating the recommendation column
      final RecommendationAccess rec_access = getDatabase().accessRec();
      final Recommendation rec = rec_access.getRec(manu.getRecommendationID());
      if (rec != null) {
        final int rating = rec.getSummaryRating();
        if (rating <= 0) {
          data[i][num_columns - 2] = "-";
        } else {
          data[i][num_columns - 2] = rating;
        } 
      }
      
      //Populating the decision columns
      data[i][num_columns - 1] = manu.getDecisionStatusString();
    }
    
    final boolean[] bools = new boolean[num_columns];
    bools[1] = true;
    
    return new CustomTable(data, headers, bools, als);
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public String getPanelLabel() {
    return "Program Chair";
  }
  
  /**
   * Builds the String for the Subprogram Chair list label.
   */
  private void buildSPCLabelText() {
    final List<Long> spcs = my_program_chair.getSubprogramChairs();
    final StringBuilder sb = new StringBuilder("Subprogram Chair");
    if (spcs.size() != 1) {
      sb.append("s");
    }
    sb.append(": ");
    if (spcs.size() >= 1) {
      final RoleAccess database = MainPage.getDatabase().accessRole();
      final Iterator<Long> itr = spcs.iterator();
      Role role = database.getRole(itr.next());
      sb.append(role.getUser().getFullName());
      while (itr.hasNext()) {
        sb.append(", ");
        role = database.getRole(itr.next());
        sb.append(role.getUser().getFullName());
      }
    }
    my_lbl_spcs.setText(sb.toString());
  }

  /**
   * Expects a User object and assigns it a Subprogram Chair role.
   * @param the_o The Object to receive.
   */
  @Override
  public void receive(final Object the_o) {
    if (the_o instanceof User) {
      final User u = (User) the_o;
      final boolean result = my_program_chair.assignSubprogramChairRole(u);
      if (result) {
        JOptionPane.showMessageDialog(this, "Successfully assigned a Subprogram Chair!");
        buildSPCLabelText();
      } else {
        JOptionPane.showMessageDialog(this, "Something went wrong...");
      }
    }
  }
  
}
